// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';

import {beforeNextRender, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

const colors = [
  // row 1
  {name: 'annotationColorBlack', color: '#000000'},
  {name: 'annotationColorRed', color: '#ff5252'},
  {name: 'annotationColorYellow', color: '#ffbc00'},
  {name: 'annotationColorGreen', color: '#00c853'},
  {name: 'annotationColorCyan', color: '#00b0ff'},
  {name: 'annotationColorPurple', color: '#d500f9'},
  {name: 'annotationColorBrown', color: '#8d6e63'},
  // row 2
  {name: 'annotationColorWhite', color: '#fafafa', outline: true},
  {name: 'annotationColorCrimson', color: '#a52714'},
  {name: 'annotationColorAmber', color: '#ee8100'},
  {name: 'annotationColorAvocadoGreen', color: '#558b2f'},
  {name: 'annotationColorCobaltBlue', color: '#01579b'},
  {name: 'annotationColorDeepPurple', color: '#8e24aa'},
  {name: 'annotationColorDarkBrown', color: '#4e342e'},
  // row 3
  {name: 'annotationColorDarkGrey', color: '#90a4ae'},
  {name: 'annotationColorHotPink', color: '#ff4081'},
  {name: 'annotationColorOrange', color: '#ff6e40'},
  {name: 'annotationColorLime', color: '#aeea00'},
  {name: 'annotationColorBlue', color: '#304ffe'},
  {name: 'annotationColorViolet', color: '#7c4dff'},
  {name: 'annotationColorTeal', color: '#1de9b6'},
  // row 4
  {name: 'annotationColorLightGrey', color: '#cfd8dc'},
  {name: 'annotationColorLightPink', color: '#f8bbd0'},
  {name: 'annotationColorLightOrange', color: '#ffccbc'},
  {name: 'annotationColorLightGreen', color: '#f0f4c3'},
  {name: 'annotationColorLightBlue', color: '#9fa8da'},
  {name: 'annotationColorLavender', color: '#d1c4e9'},
  {name: 'annotationColorLightTeal', color: '#b2dfdb'},
];

const sizes = [
  {name: 'annotationSize1', size: 0},
  {name: 'annotationSize2', size: 0.1429},
  {name: 'annotationSize3', size: 0.2857},
  {name: 'annotationSize4', size: 0.4286},
  {name: 'annotationSize8', size: 0.5714},
  {name: 'annotationSize12', size: 0.7143},
  {name: 'annotationSize16', size: 0.8571},
  {name: 'annotationSize20', size: 1},
];

// Displays a set of radio buttons to select from a predefined list of colors
// and sizes.
class ViewerPenOptionsElement extends PolymerElement {
  static get is() {
    return 'viewer-pen-options';
  }

  static get template() {
    return html`{__html_template__}`;
  }

  static get properties() {
    return {
      /** @private */
      expanded_: {
        type: Boolean,
        value: false,
      },

      selectedSize: {
        type: Number,
        value: 0.250,
        notify: true,
      },

      selectedColor: {
        type: String,
        value: '#000000',
        notify: true,
      },

      /** @private */
      sizes_: {
        type: Array,
        value: sizes,
      },

      /** @private */
      colors_: {
        type: Array,
        value: colors,
      },

      strings: Object,
    };
  }

  constructor() {
    super();

    /** @private {Array<!Animation>} */
    this.expandAnimations_ = null;
  }

  /**
   * @param {!Event} e
   * @private
   */
  sizeChanged_(e) {
    this.selectedSize = Number(e.target.value);
  }

  /**
   * @param {!Event} e
   * @private
   */
  colorChanged_(e) {
    this.selectedColor = e.target.value;
  }

  /** @private */
  toggleExpanded_() {
    this.expanded_ = !this.expanded_;
    this.updateExpandedState_();
  }

  /** @private */
  updateExpandedStateAndFinishAnimations_() {
    this.updateExpandedState_();
    for (const animation of /** @type {!Array<!Animation>} */ (
             this.expandAnimations_)) {
      animation.finish();
    }
  }

  /** @override */
  connectedCallback() {
    super.connectedCallback();
    beforeNextRender(this, () => {
      this.updateExpandedStateAndFinishAnimations_();
    });
  }

  /**
   * Updates the state of the UI to reflect the current value of `expanded`.
   * Starts or reverses animations and enables/disable controls.
   * @private
   */
  updateExpandedState_() {
    const colors = this.$.colors;
    if (!this.expandAnimations_) {
      const separator = this.$.separator;
      const expand = this.$.expand;
      this.expandAnimations_ = [
        colors.animate(
            [
              {height: '32px'},
              {height: '188px'},
            ],
            {
              easing: 'ease-in-out',
              duration: 250,
              fill: 'both',
            }),
        separator.animate(
            [
              {opacity: 0},
              {opacity: 1},
            ],
            {
              easing: 'ease-in-out',
              duration: 250,
              fill: 'both',
            }),
        expand.animate(
            [
              {transform: 'rotate(0deg)'},
              {transform: 'rotate(180deg)'},
            ],
            {
              easing: 'ease-in-out',
              duration: 250,
              fill: 'forwards',
            }),
      ];
    }
    for (const animation of this.expandAnimations_) {
      // TODO(dstockwell): Ideally we would just set playbackRate,
      // but there appears to be a web-animations bug that
      // results in the animation getting stuck in the 'pending'
      // state sometimes. See crbug.com/938857
      const currentTime = animation.currentTime;
      animation.cancel();
      animation.playbackRate = this.expanded_ ? 1 : -1;
      animation.currentTime = currentTime;
      animation.play();
    }
    for (const input of colors.querySelectorAll('input:nth-child(n+8)')) {
      input.toggleAttribute('disabled', !this.expanded_);
    }
  }

  /**
   * Used to determine equality in computed bindings.
   * @param {*} a
   * @param {*} b
   * @return {boolean} Whether a === b
   * @private
   */
  equal_(a, b) {
    return a === b;
  }

  /**
   * Used to lookup a string in a computed binding.
   * @param {Object} strings
   * @param {string} name
   * @return {string}
   * @private
   */
  lookup_(strings, name) {
    return strings ? strings[name] : '';
  }

  /**
   * Used to remove focus when clicking or tapping on a styled input
   * element. This is a workaround until we can use the :focus-visible
   * pseudo selector.
   * @param {!Event} e
   */
  blurOnPointerDown(e) {
    const target = e.target;
    setTimeout(() => target.blur(), 0);
  }
}

customElements.define(ViewerPenOptionsElement.is, ViewerPenOptionsElement);
